using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TrackSystem.IO.Data;
using TrackSystem.IO.Models;

namespace TrackSystem.IO.Protocol
{
    /// <summary>
    /// GPS通信协议 
    /// 0--纬度;
    /// 1--经度;
    /// 2--海拔高度;
    /// 3--地面速率;
    /// 4--地面航向;
    /// 5--hh UTC时间;hhmmss.sss(时分秒.毫秒)格式
    /// 6--mm 分钟
    /// 7--ss.sss 秒
    /// 8--dd UTC日期; ddmmyy(日月年)格式
    /// 9-- mm 月
    /// 10--yy 年
    /// 11--定位状态,A=有效定位，V=无效定位
    /// 12--GPS状态：0=未定位，1=非差分定位，2=差分定位，6=正在估算
    /// 13--正在使用解算位置的卫星数量（00~12）（前面的0也将被传输）
    /// 14--HDOP水平精度因子
    /// </summary>
    public class Ship2GPSProtocol : ProtocolBase
    {
        private int startTicks;
        private bool bSendR;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="name"></param>
        public Ship2GPSProtocol(string name)
            : base()
        {
            NeedInit = false;
            Name = name;
            bSendR = false;
        }

        /// <summary>
        /// 生成读取寄存器的通讯帧
        /// </summary>
        /// <returns></returns>
        public override byte[] GenerateReadFrame(out int NeedRecvLen)
        {
            startTicks = Environment.TickCount;
            if (bSendR)
            {
                Fail_R++;
                // 失败超过10次，成功次数清零
                if (Fail_R >= 10)
                {
                    Succ_R = 0;
                }
            }
            bSendR = true;
            NeedRecvLen = 40;
            return null;
        }


        /// <summary>
        /// 根据收到的内容进行处理
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public override bool ProcessReadFrame(byte[] buffer)
        {
            var DataFactory = RegFactory.Instance;
            Lapse = Environment.TickCount - startTicks;
            try
            {
                string frame = Encoding.UTF8.GetString(buffer);
                string[] ar_line = frame.Split('\n');
                try
                {
                    for (int i = 0; i < ar_line.Length; i++)
                    {
                        string[] ar_str = ar_line[i].Split(',');
                        int strLen = ar_str.Length;

                        if (strLen == 0)   // 数据长度为0
                        {
                            continue;
                        }
                        Rx_r = buffer;  // 用于显示的接收帧内容
                        // $GPGGA,< 1 >,< 2 >,< 3 >,< 4 >,< 5 >,< 6 >,< 7 >,< 8 >,< 9 >,M,< 10 >,M,< 11 >,< 12 > *hh
                        if (strLen == 15 && ar_str[0] == "$GPGGA")
                        {
                            double d1 = double.Parse(ar_str[6]); // GPS状态
                            double d2 = double.Parse(ar_str[7]); // 卫星数量
                            double d3 = double.Parse(ar_str[8]); // HDOP水平精度因子（0.5~99.9）
                            double d4 = double.Parse(ar_str[9]); // 海拔高度（-9999.9~99999.9）
                            DataFactory.SetVal(RegNameList[2], d4);
                            DataFactory.SetVal(RegNameList[12], d1);
                            DataFactory.SetVal(RegNameList[13], d2);
                            DataFactory.SetVal(RegNameList[14], d3);

                            // 和$GPGGA 重复的数据
                            double d1_h = double.Parse(ar_str[1].Substring(0, 2)); // UTC时间，hhmmss.sss(时分秒.毫秒)格式
                            double d1_m = double.Parse(ar_str[1].Substring(2, 2));
                            double d1_s = double.Parse(ar_str[1].Substring(4, ar_str[1].Length - 4));

                            // 纬度ddmm.mmmm(度分)格式(前面的0也将被传输)
                            double latDeg = double.Parse(ar_str[2].Substring(0, 2)); // 提取度
                            double latDeg2 = double.Parse(ar_str[2].Substring(2, ar_str[2].Length - 2)) / 60; // 分转化为度
                            double d_lat = Math.Round(latDeg + latDeg2, 6);
                            if (ar_str[3] == "S")
                                d_lat = -1 * d_lat;

                            // 经度dddmm.mmmm(度分)格式(前面的0也将被传输)
                            double lonDeg = double.Parse(ar_str[4].Substring(0, 3)); // 提取度
                            double lonDeg2 = double.Parse(ar_str[4].Substring(3, ar_str[4].Length - 3)) / 60; // 分转化为度
                            double d_lon = Math.Round(lonDeg + lonDeg2, 6);
                            if (ar_str[5] == "W")
                                d_lon = -1 * d_lon;

                            DataFactory.SetVal(RegNameList[0], d_lat);
                            DataFactory.SetVal(RegNameList[1], d_lon);
                            DataFactory.SetVal(RegNameList[5], d1_h);
                            DataFactory.SetVal(RegNameList[6], d1_m);
                            DataFactory.SetVal(RegNameList[7], d1_s);
                            continue;
                        }

                        // $GPRMC,< 1 >,< 2 >,< 3 >,< 4 >,< 5 >,< 6 >,< 7 >,< 8 >,< 9 >,< 10 >,< 11 >,< 12 > *hh
                        if (strLen >= 13 && ar_str[0] == "$GPRMC") {
                            double d1_h = double.Parse(ar_str[1].Substring(0,2)); // UTC时间，hhmmss.sss(时分秒.毫秒)格式
                            double d1_m = double.Parse(ar_str[1].Substring(2, 2));
                            double d1_s = double.Parse(ar_str[1].Substring(4, ar_str[1].Length-4));
                            int d2 = 0; // // 定位状态，A=有效定位，V=无效定位
                            if (ar_str[2]=="A") {
                                d2 = 1;
                            }
                            // 纬度ddmm.mmmm(度分)格式(前面的0也将被传输)
                            double latDeg = double.Parse(ar_str[3].Substring(0, 2)); // 提取度
                            double latDeg2 = double.Parse(ar_str[3].Substring(2, ar_str[3].Length-2))/60; // 分转化为度
                            double d3 = Math.Round(latDeg+ latDeg2,6);
                            if (ar_str[4] == "S")
                                d3 = -1 * d3;

                            // 经度dddmm.mmmm(度分)格式(前面的0也将被传输)
                            double lonDeg = double.Parse(ar_str[5].Substring(0, 3)); // 提取度
                            double lonDeg2 = double.Parse(ar_str[5].Substring(3, ar_str[5].Length - 3)) / 60; // 分转化为度
                            double d4 = Math.Round(lonDeg + lonDeg2, 6);
                            if (ar_str[6] == "W")
                                d4 = -1 * d4;

                            double d5 = double.Parse(ar_str[7]); // 地面速率(000.0~999.9节，前面的0也将被传输)
                            double d6 = double.Parse(ar_str[8]); // 地面航向(000.0~359.9度，以正北为参考基准，前面的0也将被传输)
                            double d7_d = double.Parse(ar_str[9].Substring(0, 2)); // UTC日期，ddmmyy(日月年)格式
                            double d7_m = double.Parse(ar_str[9].Substring(2, 2)); // UTC日期，ddmmyy(日月年)格式
                            double d7_y = double.Parse(ar_str[9].Substring(4, 2)); // UTC日期，ddmmyy(日月年)格式

                            DataFactory.SetVal(RegNameList[0], d3); 
                            DataFactory.SetVal(RegNameList[1], d4);
                            DataFactory.SetVal(RegNameList[3], d5);
                            DataFactory.SetVal(RegNameList[4], d6);
                            DataFactory.SetVal(RegNameList[5], d1_h);
                            DataFactory.SetVal(RegNameList[6], d1_m);
                            DataFactory.SetVal(RegNameList[7], d1_s);
                            DataFactory.SetVal(RegNameList[8], d7_d);
                            DataFactory.SetVal(RegNameList[9], d7_m);
                            DataFactory.SetVal(RegNameList[10], d7_y);
                            DataFactory.SetVal(RegNameList[11], d2);
                            continue;
                        }
                    }
                }
                catch (Exception)
                {
                    return false;
                }
                Succ_R++;
                // 失败次数清零
                if (Succ_R > 30 && Fail_R > 0)
                {
                    Fail_R = 0;
                }
                bSendR = false;
            }
            catch (Exception)
            {
                return false;
            }
            return true;
        }
    }
}
